require "Scene.Item.BagService"

module("BagServiceTest", package.seeall, lunit.testcase)

local player

local templateId1 = "10000"
local templateId2 = "10001"
local templateId3 = "10002"

local itemId1 = templateId1 .. "_0"
local itemId2 = templateId2 .. "_1"
local itemId3 = templateId3 .. "_" .. tostring(Util.getMiliSeconds()) .. "_0"

local itemData1
local cellData1

local itemData2
local cellData2

local itemData3
local cellData3

local bagData

function setup()
	player = { data = {} }

	itemData1 = { id = itemId1, templateId = templateId1, bind = false, data = { valid = false } }
	cellData1 = { item = itemData1, count = 4, state = CELL_STATE.DISABLE }

	itemData2 = { id = itemId2, templateId = templateId2, bind = true, data = { valid = false } }
	cellData2 = { item = itemData2, count = 4, state = CELL_STATE.ENABLE }

	itemData3 = { id = itemId3, templateId = templateId3, bind = false, data = { valid = false } }
	cellData3 = { item = itemData3, count = 1, state = CELL_STATE.ENABLE }

	bagData = { capacity = 50, cells = { ["1"] = cellData1, ["2"] = cellData2, ["3"] = cellData3 } }
end

function teardown()
end

function test_initialize()
	BagService.initialize(player)

	assert_equal(25, BagService.getCapacity(player))
	assert_equal(0, BagService.getCellCount(player))

	player.data.b_bag = bagData
	BagService.initialize(player)

	assert_equal(50, BagService.getCapacity(player))
	assert_equal(3, BagService.getCellCount(player))
end

function test_flush()
	BagService.initialize(player)

	assert_nil(player.data.b_bag)

	BagService.flush(player)

	assert_equal(25, player.data.b_bag.capacity)
end

function test_clear()
	player.data.b_bag = bagData
	BagService.initialize(player)

	BagService.clear(player)

	assert_equal(0, BagService.getCellCount(player))

	local request = Client.getTailRequest(player)

	assert_equal("clearBagCells", request.request)
end

function test_extend()
	BagService.initialize(player)

	assert_false(BagService.extend(player, -1))
	assert_false(BagService.extend(player, 0))
	assert_false(BagService.extend(player, 50))

	assert_true(BagService.extend(player, 25))

	assert_equal(50, BagService.getCapacity(player))

	local request = Client.getTailRequest(player)

	assert_equal("updateBagCapacity", request.request)
	assert_equal(50, request.arguments[1])
end

function test_getCell()
	BagService.initialize(player)

	assert_nil(BagService.getCell(player, "1"))

	player.data.b_bag = bagData
	BagService.initialize(player)

	assert_nil(BagService.getCell(player, "1"))

	assert_not_nil(BagService.getCell(player, "2"))
	assert_not_nil(BagService.getCell(player, "3"))
end

function test_setState()
	BagService.initialize(player)

	assert_equal(CELL_STATE.DISABLE, BagService.getState(player, "1"))
	assert_false(BagService.setState(player, "1", CELL_STATE.ENABLE))

	player.data.b_bag = bagData
	BagService.initialize(player)

	assert_equal(CELL_STATE.DISABLE, BagService.getState(player, "1"))
	assert_true(BagService.setState(player, "1", CELL_STATE.ENABLE))

	local request = Client.getTailRequest(player)

	assert_equal("updateBagState", request.request)
	assert_equal("1", request.arguments[1])
	assert_equal(CELL_STATE.ENABLE, request.arguments[2])
end

function test_bindItem()
	player.data.b_bag = bagData
	BagService.initialize(player)

	assert_false(BagService.bindItem(player, "1"))
	assert_false(BagService.bindItem(player, "2"))

	assert_true(BagService.bindItem(player, "3"))
end

function test_refreshItem()
	player.data.b_bag = bagData
	BagService.initialize(player)

	local item = BagService.getCell(player, "2").item
	item.data = { valid = true }

	BagService.refreshItem(player, "2")

	local request = Client.getTailRequest(player)

	assert_equal("updateBagItem", request.request)
	assert_equal("2", request.arguments[1])
	assert_true(request.arguments[2].data.valid)
end

function test_getItemCount()
	BagService.initialize(player)

	assert_equal(0, BagService.getItemCount(player, templateId1))
	assert_equal(0, BagService.getItemCount(player, templateId2))
	assert_equal(0, BagService.getItemCount(player, templateId3))

	player.data.b_bag = bagData
	BagService.initialize(player)

	assert_equal(4, BagService.getItemCount(player, templateId1))
	assert_equal(4, BagService.getItemCount(player, templateId2))
	assert_equal(1, BagService.getItemCount(player, templateId3))
end

function test_canAddItem()
	local item1 = ItemService.newItem(templateId1, false)
	local item2 = ItemService.newItem(templateId2, false)
	local item3 = ItemService.newItem(templateId3, false)

	local reservedSlots

	-- add item with accmulation, multi add
	BagService.initialize(player)

	reservedSlots = {}
	assert_false(BagService.canAddItem(player, item1, -1, reservedSlots))
	assert_false(BagService.canAddItem(player, item1, 0, reservedSlots))

	assert_true(BagService.canAddItem(player, item1, 1, reservedSlots))
	assert_true(BagService.canAddItem(player, item1, 124, reservedSlots))
	assert_false(BagService.canAddItem(player, item1, 1, reservedSlots))

	-- add item without accmulation, multi add
	BagService.initialize(player)

	reservedSlots = {}
	assert_error_match("Add invalid count", function() BagService.canAddItem(player, item3, 2, reservedSlots) end)

	assert_true(BagService.canAddItem(player, item3, 1, reservedSlots))
	assert_error_match("Add existed item", function() BagService.canAddItem(player, item3, 1, reservedSlots) end)

	-- add item with disable cell, multi add
	player.data.b_bag = bagData
	BagService.initialize(player)

	reservedSlots = {}
	assert_true(BagService.canAddItem(player, item1, 1, reservedSlots))
	assert_false(BagService.canAddItem(player, item1, 235, reservedSlots))

	-- add item with bind item, multi add
	player.data.b_bag = bagData
	BagService.initialize(player)

	reservedSlots = {}
	assert_true(BagService.canAddItem(player, item2, 1, reservedSlots))
	assert_false(BagService.canAddItem(player, item2, 235, reservedSlots))
end

function test_canAddItems()
	local item1 = ItemService.newItem(templateId1, false)
	local item2 = ItemService.newItem(templateId2, false)
	local item3 = ItemService.newItem(templateId3, false)

	BagService.initialize(player)

	local itemTable = {}
	local reservedSlots = {}

	assert_false(BagService.canAddItems(player, itemTable, reservedSlots))

	itemTable[item1] = 1

	assert_true(BagService.canAddItems(player, itemTable, reservedSlots))

	itemTable[item1] = 49
	itemTable[item2] = 50
	itemTable[item3] = 1

	assert_true(BagService.canAddItems(player, itemTable, reservedSlots))

	itemTable[item1] = nil
	itemTable[item2] = nil
	itemTable[item3] = 1

	assert_error_match("Add existed item", function() BagService.canAddItems(player, itemTable, reservedSlots) end)
end

function test_canDeleteCell()
	player.data.b_bag = bagData
	BagService.initialize(player)

	local deleteSlots = {}
	assert_false(BagService.canDeleteCell(player, "2", -1, deleteSlots))
	assert_false(BagService.canDeleteCell(player, "2", 0, deleteSlots))

	assert_true(BagService.canDeleteCell(player, "2", 1, deleteSlots))
	assert_true(BagService.canDeleteCell(player, "2", 3, deleteSlots))

	assert_false(BagService.canDeleteCell(player, "2", 1, deleteSlots))
end

function test_canDeleteItem()
	player.data.b_bag = bagData
	BagService.initialize(player)

	local deleteSlots = {}
	assert_false(BagService.canDeleteItem(player, templateId2, -1, deleteSlots))
	assert_false(BagService.canDeleteItem(player, templateId2, 0, deleteSlots))

	assert_true(BagService.canDeleteItem(player, templateId2, 1, deleteSlots))
	assert_true(BagService.canDeleteItem(player, templateId2, 3, deleteSlots))

	assert_false(BagService.canDeleteItem(player, templateId2, 1, deleteSlots))
end

function test_canDeleteItems()
	player.data.b_bag = bagData
	BagService.initialize(player)

	local templateTable = {}
	local deleteSlots = {}

	assert_false(BagService.canDeleteItems(player, templateTable, deleteSlots))

	templateTable[templateId2] = 4
	templateTable[templateId3] = 1

	assert_true(BagService.canDeleteItems(player, templateTable, deleteSlots))

	assert_false(BagService.canDeleteItems(player, templateTable, deleteSlots))
end

function test_addIems()
	local item1 = ItemService.newItem(templateId1, false)
	local item2 = ItemService.newItem(templateId2, false)
	local item3 = ItemService.newItem(templateId3, false)

	BagService.initialize(player)

	local itemTable = {}
	local reservedSlots = {}

	itemTable[item1] = 50
	itemTable[item2] = 50
	itemTable[item3] = 1

	assert_true(BagService.canAddItems(player, itemTable, reservedSlots))

	BagService.addItems(player, reservedSlots)

	assert_equal(21, BagService.getCellCount(player))
end

function test_deleteItems()
	player.data.b_bag = bagData
	BagService.initialize(player)

	local templateTable = {}
	local deletedSlots = {}

	templateTable[templateId2] = 4
	templateTable[templateId3] = 1

	assert_true(BagService.canDeleteItems(player, templateTable, deletedSlots))

	BagService.deleteItems(player, deletedSlots)

	assert_equal(1, BagService.getCellCount(player))
end

function test_sort()
	player.data.b_bag = bagData
	BagService.initialize(player)

	BagService.sort(player)

	local request = Client.getTailRequest(player)

	assert_equal("updateBagData", request.request)
end

function test_divideCell()
	player.data.b_bag = bagData
	BagService.initialize(player)

	assert_false(BagService.divideCell(player, "1", 1))

	assert_false(BagService.divideCell(player, "2", -1))
	assert_false(BagService.divideCell(player, "2", 0))
	assert_false(BagService.divideCell(player, "2", 5))

	assert_true(BagService.divideCell(player, "2", 1))

	assert_equal(4, BagService.getCellCount(player))
	assert_equal(4, BagService.getItemCount(player, templateId2))
end

function test_moveCell()
	player.data.b_bag = bagData
	BagService.initialize(player)

	assert_false(BagService.moveCell(player, "1", "4"))

	assert_true(BagService.moveCell(player, "2", "4"))

	assert_nil(BagService.getCell(player, "2"))
	assert_equal(itemId2, BagService.getCell(player, "4").item.id)

	assert_true(BagService.moveCell(player, "3", "4"))

	assert_equal(itemId3, BagService.getCell(player, "4").item.id)
end

function test_useCell()
	player.data.b_bag = bagData
	BagService.initialize(player)

	assert_false(BagService.useCell(player, "1", 4, true, 1, 0.1, "string"))
	assert_false(BagService.useCell(player, "2", 4, true, 1, 0.1, "string"))
	assert_false(BagService.useCell(player, "3", 1, true, 1, 0.1, "string"))
end

function test_useItem()
	player.data.b_bag = bagData
	BagService.initialize(player)

	assert_false(BagService.useItem(player, templateId1, 4, true, 1, 0.1, "string"))
	assert_false(BagService.useItem(player, templateId2, 4, true, 1, 0.1, "string"))
	assert_false(BagService.useItem(player, templateId3, 1, true, 1, 0.1, "string"))
end